cmake_minimum_required(VERSION 3.20)
set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "Allow older policy versions for third-party deps")
project(sokoban3d LANGUAGES CXX)

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

option(SOKO3D_BUILD_TESTS "Build unit tests" ON)
option(SOKO3D_ENABLE_GLFW "Enable GLFW window for app" ON)
option(SOKO3D_ENABLE_IMGUI "Enable Dear ImGui overlay" ON)
option(SOKO3D_STATIC_RUNTIME "Link libstdc++/libgcc statically on MinGW" ON)

file(GLOB_RECURSE CORE_SOURCES CONFIGURE_DEPENDS src/core/*.cpp)
file(GLOB_RECURSE CORE_HEADERS CONFIGURE_DEPENDS include/*.h src/core/*.h)

add_library(sokoban3d_core ${CORE_SOURCES} ${CORE_HEADERS})
target_include_directories(sokoban3d_core PUBLIC include src)

add_executable(sokoban3d_app
  src/app/main.cpp
  src/app/LevelLoader.cpp
  src/render/Shader.cpp
  src/render/Mesh.cpp
  src/render/Camera.cpp
  src/render/Renderer.cpp
)
target_include_directories(sokoban3d_app PRIVATE src)
target_link_libraries(sokoban3d_app PRIVATE sokoban3d_core)

if(SOKO3D_ENABLE_GLFW)
  include(FetchContent)
  set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
  FetchContent_Declare(glad
    GIT_REPOSITORY https://github.com/Dav1dde/glad.git
    GIT_TAG v0.1.36
  )
  FetchContent_Declare(glm
    GIT_REPOSITORY https://github.com/g-truc/glm.git
    GIT_TAG 0.9.9.8
  )
  set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
  set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
  set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
  set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
  FetchContent_Declare(glfw
    GIT_REPOSITORY https://github.com/glfw/glfw.git
    GIT_TAG 3.3.9
  )
  if(SOKO3D_ENABLE_IMGUI)
    FetchContent_Declare(imgui
      GIT_REPOSITORY https://github.com/ocornut/imgui.git
      GIT_TAG v1.90.8
    )
    FetchContent_MakeAvailable(glad glm glfw imgui)
    add_library(imgui_obj
      ${imgui_SOURCE_DIR}/imgui.cpp
      ${imgui_SOURCE_DIR}/imgui_draw.cpp
      ${imgui_SOURCE_DIR}/imgui_tables.cpp
      ${imgui_SOURCE_DIR}/imgui_widgets.cpp
      ${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
      ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
    )
    target_include_directories(imgui_obj PUBLIC ${imgui_SOURCE_DIR} ${imgui_SOURCE_DIR}/backends)
    target_compile_definitions(imgui_obj PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLAD)
    target_link_libraries(imgui_obj PUBLIC glfw glad)
  else()
    FetchContent_MakeAvailable(glad glm glfw)
  endif()
  find_package(OpenGL REQUIRED)
  target_link_libraries(sokoban3d_app PRIVATE glfw glad OpenGL::GL)
  target_link_libraries(sokoban3d_app PRIVATE glm)
  if(SOKO3D_ENABLE_IMGUI)
    target_link_libraries(sokoban3d_app PRIVATE imgui_obj)
    target_compile_definitions(sokoban3d_app PRIVATE SOKO3D_USE_IMGUI=1)
  endif()
  target_compile_definitions(sokoban3d_app PRIVATE SOKO3D_USE_GLFW=1)
  if(MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND SOKO3D_STATIC_RUNTIME)
    target_link_options(sokoban3d_app PRIVATE -static -static-libstdc++ -static-libgcc)
  endif()
endif()

if(SOKO3D_BUILD_TESTS)
  enable_testing()
  add_executable(sokoban3d_tests tests/test_core.cpp)
  target_link_libraries(sokoban3d_tests PRIVATE sokoban3d_core)
  add_test(NAME core_tests COMMAND sokoban3d_tests)
endif()